﻿#include "framework.h"
#include <commctrl.h>
#include "Const.h"
#include "InputBox.h"
#include "MainWindow.h"
#include "Resource.h"

// 函数声明
static void MainWindow_Delete(MainWindow*);
static void MainWindow_DoModal(MainWindow*);
static void MainWindow_OnGameOver(MainWindow*, BOOL);
static void MainWindow_OnGotoLevel(MainWindow*, int);
static BOOL MainWindow_OnKeyPressed(MainWindow*, UINT);
static void MainWindow_OnManMoved(MainWindow*, int);
static void MainWindow_OnMenuItemRestartClicked(MainWindow*);
static void MainWindow_OnMenuItemSelectLevelClicked(MainWindow*);
static void MainWindow_OnMenuItemUndoClicked(MainWindow*);
static INT_PTR CALLBACK MainWindow_Proc(HWND, UINT, WPARAM, LPARAM);

/**
 * 创建主窗口。
 * @return 主窗口
 */
MainWindow* New_MainWindow() {
    RECT rect = { 0 };
    int parts[STATUS_BAR_PART_COUNT] = { 0 };
    MainWindow* mainWindow = (MainWindow*)calloc(1, sizeof(MainWindow));

    // 初始化数据
    mainWindow->mHandle = CreateDialog(NULL, MAKEINTRESOURCE(IDD_MAIN_WINDOW), NULL, MainWindow_Proc);
    SetWindowLongPtr(mainWindow->mHandle, GWLP_USERDATA, (LONG_PTR)mainWindow);
    mainWindow->mStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM, NULL, mainWindow->mHandle, 0);

    // 初始化函数
    mainWindow->doModal = MainWindow_DoModal;

    // 设置状态栏
    GetWindowRect(mainWindow->mHandle, &rect);
    parts[0] = (rect.right - rect.left) / STATUS_BAR_PART_COUNT;
    parts[1] = rect.right - rect.left;
    SendMessage(mainWindow->mStatusBar, SB_SETPARTS, STATUS_BAR_PART_COUNT, (LPARAM)parts);

    // 创建游戏区域
    mainWindow->mGameBoard = New_GameBoard(mainWindow->mHandle, GAME_BOARD_X, GAME_BOARD_Y, GAME_BOARD_WIDTH, GAME_BOARD_HEIGHT);

    // 创建游戏
    mainWindow->mGame = New_Game(mainWindow->mHandle, mainWindow->mGameBoard->mDrawer, mainWindow->mGameBoard->mHandle);

    return mainWindow;
}

/**
 * 删除主窗口。
 * @param mainWindow    主窗口
 */
static void MainWindow_Delete(MainWindow* mainWindow) {
    mainWindow->mGame->deleteSelf(mainWindow->mGame);
    mainWindow->mGameBoard->deleteSelf(mainWindow->mGameBoard);
    DestroyWindow(mainWindow->mStatusBar);
    DestroyWindow(mainWindow->mHandle);
    free(mainWindow);
}

/**
 * 以模态显示窗口。
 * @param mainWindow    主窗口
 */
static void MainWindow_DoModal(MainWindow* mainWindow) {
    MSG msg = { 0 };
    BOOL handledKeyPress = FALSE;

    // 显示窗口
    ShowWindow(mainWindow->mHandle, SW_SHOW);

    // 窗口事件循环
    while (GetMessage(&msg, NULL, 0, 0)) {
        if (msg.message == WM_KEYDOWN) {
            handledKeyPress = MainWindow_OnKeyPressed(mainWindow, (UINT)msg.wParam);
        }
        if (!handledKeyPress) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        handledKeyPress = FALSE;
    }
}

/**
 * 游戏结束事件的响应函数。
 * @param mainWindow    主窗口
 * @param allOver       全部通关则为 TRUE，否则为 FALSE
 */
static void MainWindow_OnGameOver(MainWindow* mainWindow, BOOL allOver) {
    TCHAR text[STRING_BUF_LEN] = { 0 };
    if (allOver) {
        LoadString(NULL, IDS_WON_ALL_OVER, text, STRING_BUF_LEN);
    } else {
        LoadString(NULL, IDS_WON, text, STRING_BUF_LEN);
    }
    MessageBox(mainWindow->mHandle, text, _T(" "), MB_ICONINFORMATION);
}

/**
 * 进入关卡事件的响应函数。
 * @param mainWindow    主窗口
 * @param level         关卡数
 */
static void MainWindow_OnGotoLevel(MainWindow* mainWindow, int level) {
    TCHAR format[STRING_BUF_LEN] = { 0 };
    TCHAR text[STRING_BUF_LEN] = { 0 };

    LoadString(NULL, IDS_LEVEL, format, STRING_BUF_LEN);
    _stprintf_s(text, STRING_BUF_LEN, format, level);
    SendMessage(mainWindow->mStatusBar, SB_SETTEXT, 0, (LPARAM)text);

    LoadString(NULL, IDS_MOVE_COUNT, format, STRING_BUF_LEN);
    _stprintf_s(text, STRING_BUF_LEN, format, 0);
    SendMessage(mainWindow->mStatusBar, SB_SETTEXT, 1, (LPARAM)text);
}

/**
 * 按键事件的响应函数。
 * @param mainWindow    主窗口
 * @param key           按键
 * @return 事件在此被处理则返回 TRUE，否则返回 FALSE
 */
static BOOL MainWindow_OnKeyPressed(MainWindow* mainWindow, UINT key) {
    return mainWindow->mGame->onKeyPressed(mainWindow->mGame, key);
}

/**
 * 小人移动事件的响应函数。
 * @param mainWindow    主窗口
 * @param moveCount     小人移动次数
 */
static void MainWindow_OnManMoved(MainWindow* mainWindow, int moveCount) {
    TCHAR text[STRING_BUF_LEN] = { 0 };
    TCHAR format[STRING_BUF_LEN] = { 0 };

    LoadString(NULL, IDS_MOVE_COUNT, format, STRING_BUF_LEN);
    _stprintf_s(text, STRING_BUF_LEN, format, moveCount);
    SendMessage(mainWindow->mStatusBar, SB_SETTEXT, 1, (LPARAM)text);
}

/**
 * "重玩本关"菜单项的单击响应函数。
 * @param mainWindow    主窗口
 */
static void MainWindow_OnMenuItemRestartClicked(MainWindow* mainWindow) {
    mainWindow->mGame->restart(mainWindow->mGame);
}

/**
 * "选关"菜单项的单击响应函数。
 * @param mainWindow    主窗口
 */
static void MainWindow_OnMenuItemSelectLevelClicked(MainWindow* mainWindow) {
    TCHAR tipText[STRING_BUF_LEN] = { 0 };
    TCHAR format[STRING_BUF_LEN] = { 0 };
    InputBox* inputBox = NULL;
    
    // 显示输入窗口
    LoadString(NULL, IDS_PLEASE_INPUT_NUMBER, format, STRING_BUF_LEN);
    _stprintf_s(tipText, STRING_BUF_LEN, format, mainWindow->mGame->mLevel, LEVEL_COUNT);
    inputBox = New_InputBox_Int(mainWindow->mGame->mLevel, LEVEL_COUNT, 1, mainWindow->mHandle, tipText);
    if (inputBox->doModal(inputBox) == IDCANCEL) {
        return;
    }

    // 进入关卡
    if (inputBox->mIntValue != mainWindow->mGame->mLevel) {
        mainWindow->mGame->gotoLevel(mainWindow->mGame, inputBox->mIntValue);
    }
    free(inputBox);
}

/**
 * "回退"菜单项的单击响应函数。
 * @param mainWindow    主窗口
 */
static void MainWindow_OnMenuItemUndoClicked(MainWindow* mainWindow) {
    mainWindow->mGame->undo(mainWindow->mGame);
}

/**
 * 窗口过程函数。
 * @param window    窗口
 * @param message   事件标识
 * @param wParam    事件相关信息
 * @param lParam    事件相关信息
 * @return 事件在此被处理则返回 TRUE，否则返回 FALSE
 */
static INT_PTR CALLBACK MainWindow_Proc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) {
    MainWindow* mainWindow = (MainWindow*)GetWindowLongPtr(window, GWLP_USERDATA);
    WORD id = LOWORD(wParam);
    UNREFERENCED_PARAMETER(lParam);

    switch (message) {
        case UM_GAME_OVER:
            MainWindow_OnGameOver(mainWindow, (BOOL)wParam);
            return TRUE;
        case UM_GOTO_LEVEL:
            MainWindow_OnGotoLevel(mainWindow, (int)wParam);
            return TRUE;
        case UM_MAN_MOVED:
            MainWindow_OnManMoved(mainWindow, (int)wParam);
            return TRUE;
        case WM_COMMAND:
            switch (id) {
                case IDC_MENU_ITEM_RESTART:
                    MainWindow_OnMenuItemRestartClicked(mainWindow);
                    break;
                case IDC_MENU_ITEM_SELECT_LEVEL:
                    MainWindow_OnMenuItemSelectLevelClicked(mainWindow);
                    break;
                case IDC_MENU_ITEM_UNDO:
                    MainWindow_OnMenuItemUndoClicked(mainWindow);
                    break;
                case IDCANCEL:
                    MainWindow_Delete(mainWindow);
                    break;
            }
            return TRUE;
        case WM_DESTROY:
            PostQuitMessage(0);
            return TRUE;
    }
    return FALSE;
}
